<!-- This Source Code Form is subject to the terms of the Mozilla Public
   - License, v. 2.0. If a copy of the MPL was not distributed with this
   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE HTML>
<html>
<!--
Test grip rep
-->
<head>
  <meta charset="utf-8">
  <title>Rep test - grip</title>
  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
  let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
  let { Grip } = browserRequire("devtools/client/shared/components/reps/grip");

  const componentUnderTest = Grip;

  try {
    yield testBasic();
    yield testBooleanObject();
    yield testNumberObject();
    yield testStringObject();
    yield testProxy();
    yield testArrayBuffer();
    yield testSharedArrayBuffer();

    // Test property iterator
    yield testMaxProps();
    yield testMoreThanMaxProps();
    yield testUninterestingProps();
    yield testNonEnumerableProps();

    // Test that properties are rendered as expected by PropRep
    yield testNestedObject();
    yield testNestedArray();

    // Test that 'more' property doesn't clobber the caption.
    yield testMoreProp();
  } catch(e) {
    ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
  } finally {
    SimpleTest.finish();
  }

  function testBasic() {
    // Test object: `{}`
    const testName = "testBasic";

    // Test that correct rep is chosen
    const gripStub = getGripStub("testBasic");
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `Object {  }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testBooleanObject() {
    // Test object: `new Boolean(true)`
    const testName = "testBooleanObject";

    // Test that correct rep is chosen
    const gripStub = getGripStub(testName);
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `Boolean { true }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Boolean`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testNumberObject() {
    // Test object: `new Number(42)`
    const testName = "testNumberObject";

    // Test that correct rep is chosen
    const gripStub = getGripStub(testName);
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `Number { 42 }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Number`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testStringObject() {
    // Test object: `new String("foo")`
    const testName = "testStringObject";

    // Test that correct rep is chosen
    const gripStub = getGripStub(testName);
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `String { "foo" }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `String`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testProxy() {
    // Test object: `new Proxy({a:1},[1,2,3])`
    const testName = "testProxy";

    // Test that correct rep is chosen
    const gripStub = getGripStub(testName);
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `Proxy { <target>: Object, <handler>: [3] }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Proxy`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testArrayBuffer() {
    // Test object: `new ArrayBuffer(10)`
    const testName = "testArrayBuffer";

    // Test that correct rep is chosen
    const gripStub = getGripStub(testName);
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `ArrayBuffer { byteLength: 10 }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `ArrayBuffer`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testSharedArrayBuffer() {
    // Test object: `new SharedArrayBuffer(5)`
    const testName = "testSharedArrayBuffer";

    // Test that correct rep is chosen
    const gripStub = getGripStub(testName);
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `SharedArrayBuffer { byteLength: 5 }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `SharedArrayBuffer`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testMaxProps() {
    // Test object: `{a: "a", b: "b", c: "c"}`;
    const testName = "testMaxProps";

    const defaultOutput = `Object { a: "a", b: "b", c: "c" }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testMoreThanMaxProps() {
    // Test object = `{p0: "0", p1: "1", p2: "2", …, p100: "100"}`
    const testName = "testMoreThanMaxProps";

    const defaultOutput = `Object { p0: "0", p1: "1", p2: "2", 98 more… }`;

    // Generate string with 100 properties, which is the max limit
    // for 'long' mode.
    let props = "";
    for (let i = 0; i < 100; i++) {
      props += "p" + i + ": \"" + i + "\", ";
    }

    const longOutput = `Object { ${props}1 more… }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: longOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testUninterestingProps() {
    // Test object: `{a: undefined, b: undefined, c: "c", d: 1}`
    // @TODO This is not how we actually want the preview to be output.
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=1276376
    const expectedOutput = `Object { a: undefined, b: undefined, c: "c", 1 more… }`;
  }

  function testNonEnumerableProps() {
    // Test object: `Object.defineProperty({}, "foo", {enumerable : false});`
    const testName = "testNonEnumerableProps";

    // Test that correct rep is chosen
    const gripStub = getGripStub("testNonEnumerableProps");
    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);

    // Test rendering
    const defaultOutput = `Object {  }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testNestedObject() {
    // Test object: `{objProp: {id: 1}, strProp: "test string"}`
    const testName = "testNestedObject";

    const defaultOutput = `Object { objProp: Object, strProp: "test string" }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testNestedArray() {
    // Test object: `{arrProp: ["foo", "bar", "baz"]}`
    const testName = "testNestedArray";

    const defaultOutput = `Object { arrProp: [3] }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: defaultOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function testMoreProp() {
    // Test object: `{a: undefined, b: 1, more: 2, d: 3}`;
    const testName = "testMoreProp";

    const defaultOutput = `Object { b: 1, more: 2, d: 3, 1 more… }`;
    const longOutput = `Object { a: undefined, b: 1, more: 2, d: 3 }`;

    const modeTests = [
      {
        mode: undefined,
        expectedOutput: defaultOutput,
      },
      {
        mode: "tiny",
        expectedOutput: `Object`,
      },
      {
        mode: "short",
        expectedOutput: defaultOutput,
      },
      {
        mode: "long",
        expectedOutput: longOutput,
      }
    ];

    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
  }

  function getGripStub(functionName) {
    switch (functionName) {
      case "testBasic":
        return {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj304",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 0,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 0,
            "safeGetterValues": {}
          }
        };

      case "testMaxProps":
        return {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj337",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 3,
          "preview": {
            "kind": "Object",
            "ownProperties": {
              "a": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": "a"
              },
              "b": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": "b"
              },
              "c": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": "c"
              }
            },
            "ownPropertiesLength": 3,
            "safeGetterValues": {}
          }
        };

      case "testMoreThanMaxProps": {
        let grip = {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj332",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 101,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 101,
            "safeGetterValues": {}
          }
        };

        // Generate 101 properties, which is more that the maximum
        // limit in case of the 'long' mode.
        for (let i = 0; i < 101; i++) {
          grip.preview.ownProperties["p" + i] = {
            "configurable": true,
            "enumerable": true,
            "writable": true,
            "value": i + ""
          };
        }

        return grip;
      }

      case "testUninterestingProps":
        return {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj342",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 4,
          "preview": {
            "kind": "Object",
            "ownProperties": {
              "a": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": {
                  "type": "undefined"
                }
              },
              "b": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": {
                  "type": "undefined"
                }
              },
              "c": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": "c"
              },
              "d": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": 1
              }
            },
            "ownPropertiesLength": 4,
            "safeGetterValues": {}
          }
        };
      case "testNonEnumerableProps":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj30",
          "class": "Object",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 1,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 1,
            "safeGetterValues": {}
          }
        };
      case "testNestedObject":
        return {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj145",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 2,
          "preview": {
            "kind": "Object",
            "ownProperties": {
              "objProp": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": {
                  "type": "object",
                  "class": "Object",
                  "actor": "server1.conn0.obj146",
                  "extensible": true,
                  "frozen": false,
                  "sealed": false,
                  "ownPropertyLength": 1
                }
              },
              "strProp": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": "test string"
              }
            },
            "ownPropertiesLength": 2,
            "safeGetterValues": {}
          }
        };

      case "testNestedArray":
        return {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj326",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 1,
          "preview": {
            "kind": "Object",
            "ownProperties": {
              "arrProp": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": {
                  "type": "object",
                  "class": "Array",
                  "actor": "server1.conn0.obj327",
                  "extensible": true,
                  "frozen": false,
                  "sealed": false,
                  "ownPropertyLength": 4,
                  "preview": {
                    "kind": "ArrayLike",
                    "length": 3
                  }
                }
              }
            },
            "ownPropertiesLength": 1,
            "safeGetterValues": {}
          },
        };

      case "testMoreProp":
        return {
          "type": "object",
          "class": "Object",
          "actor": "server1.conn0.obj342",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 4,
          "preview": {
            "kind": "Object",
            "ownProperties": {
              "a": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": {
                  "type": "undefined"
                }
              },
              "b": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": 1
              },
              "more": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": 2
              },
              "d": {
                "configurable": true,
                "enumerable": true,
                "writable": true,
                "value": 3
              }
            },
            "ownPropertiesLength": 4,
            "safeGetterValues": {}
          }
        };
      case "testBooleanObject":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj57",
          "class": "Boolean",
          "ownPropertyLength": 0,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 0,
            "safeGetterValues": {},
            "wrappedValue": true
          }
        };
      case "testNumberObject":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj59",
          "class": "Number",
          "ownPropertyLength": 0,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 0,
            "safeGetterValues": {},
            "wrappedValue": 42
          }
        };
      case "testStringObject":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj61",
          "class": "String",
          "ownPropertyLength": 4,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 4,
            "safeGetterValues": {},
            "wrappedValue": "foo"
          }
        };
      case "testProxy":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj47",
          "class": "Proxy",
          "proxyTarget": {
            "type": "object",
            "actor": "server1.conn1.child1/obj48",
            "class": "Object",
            "ownPropertyLength": 1
          },
          "proxyHandler": {
            "type": "object",
            "actor": "server1.conn1.child1/obj49",
            "class": "Array",
            "ownPropertyLength": 4,
            "preview": {
              "kind": "ArrayLike",
              "length": 3
            }
          },
          "preview": {
            "kind": "Object",
            "ownProperties": {
              "<target>": {
                "value": {
                  "type": "object",
                  "actor": "server1.conn1.child1/obj48",
                  "class": "Object",
                  "ownPropertyLength": 1
                }
              },
              "<handler>": {
                "value": {
                  "type": "object",
                  "actor": "server1.conn1.child1/obj49",
                  "class": "Array",
                  "ownPropertyLength": 4,
                  "preview": {
                    "kind": "ArrayLike",
                    "length": 3
                  }
                }
              }
            },
            "ownPropertiesLength": 2
          }
        };
      case "testArrayBuffer":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj170",
          "class": "ArrayBuffer",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 0,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 0,
            "safeGetterValues": {
              "byteLength": {
                "getterValue": 10,
                "getterPrototypeLevel": 1,
                "enumerable": false,
                "writable": true
              }
            }
          }
        };
      case "testSharedArrayBuffer":
        return {
          "type": "object",
          "actor": "server1.conn1.child1/obj171",
          "class": "SharedArrayBuffer",
          "extensible": true,
          "frozen": false,
          "sealed": false,
          "ownPropertyLength": 0,
          "preview": {
            "kind": "Object",
            "ownProperties": {},
            "ownPropertiesLength": 0,
            "safeGetterValues": {
              "byteLength": {
                "getterValue": 5,
                "getterPrototypeLevel": 1,
                "enumerable": false,
                "writable": true
              }
            }
          }
        };
    }
  }
});
</script>
</pre>
</body>
</html>
